﻿using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public class CommandExecutor
{
    private readonly List<string> _commands = new();
    private ProcessStartInfo _startInfo = new()
    {
        FileName = OperatingSystem.IsWindows() ? "cmd.exe" : "/bin/bash",
        UseShellExecute = false,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        CreateNoWindow = true,
    };

    // 添加命令（链式调用）
    public CommandExecutor AddCommand(string command)
    {
        _commands.Add(command);
        return this;
    }

    // 异步执行命令序列
    public async Task<ExecutionResult> ExecuteAsync(CancellationToken ct = default)
    {
        using var process = new Process { StartInfo = _startInfo };
        var output = new StringBuilder();
        var error = new StringBuilder();

        // 输出处理事件
        process.OutputDataReceived += (_, e) =>
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                output.AppendLine(e.Data);
                Console.WriteLine(e.Data);
            }
        };

        process.ErrorDataReceived += (_, e) =>
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                error.AppendLine(e.Data);
                Console.WriteLine(e.Data);
            }
        };

        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        // 发送命令序列
        using (var writer = process.StandardInput)
        {
            if (writer.BaseStream.CanWrite)
            {
                foreach (var cmd in _commands)
                {
                    await writer.WriteLineAsync(cmd.AsMemory(), ct);
                }
                await writer.WriteLineAsync("exit".AsMemory(), ct); // 确保退出[1](@ref)
            }
        }

        // 等待退出
        await process.WaitForExitAsync(ct);
        return new ExecutionResult(
            process.ExitCode,
            output.ToString(),
            error.ToString()
        );
    }

    public record ExecutionResult(int ExitCode, string Output, string Error);


    private static async Task Main()
    {
        var buildDir = Path.GetDirectoryName(typeof(CommandExecutor).Assembly.Location) ?? throw new InvalidOperationException();
        var fullName = new DirectoryInfo(buildDir).Parent?.Parent?.Parent?.Parent?.FullName ?? throw new InvalidOperationException();
        var projectFile = Path.Combine(fullName, "FlyingEye.DeviceAppService\\FlyingEye.DeviceAppService.csproj");

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(projectFile);

        var version = xmlDocument.SelectSingleNode("Project/PropertyGroup/ApplicationVersion")?.InnerText
            ?? throw new InvalidOperationException("未设置版本号");

        var appName = "DeviceAppService-v" + version;
        var binDir = new DirectoryInfo(buildDir)?.Parent?.Parent?.FullName ?? throw new InvalidOperationException();
        Console.WriteLine("开始打包软件 " + appName + " ...");

        var appDir = Path.Combine(binDir, appName);
        var publishCommand = $"dotnet publish {projectFile} -c Release -r linux-x64 -o {appDir}";
        var currentProjectDir = Directory.GetParent(binDir)?.FullName ?? throw new InvalidOperationException();

        var packagePath = Path.Combine(binDir, appName + ".tar");
        var packCommand = $"tar -cf {packagePath} -C {binDir} {appName}";

        // 执行构建打包
        var executor = new CommandExecutor()
            .AddCommand(publishCommand)
            .AddCommand(packCommand)
            .AddCommand($"explorer {binDir}")
            ;

        var result = await executor.ExecuteAsync();
        Console.WriteLine($"Exit Code: {result.ExitCode}");
    }
}

